/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include "网格.h"
#include <B_几何图形/三角形.h>
#include <几何图形/图形相交.h>
#include <ppl.h>

#include "底层绘图/底层绘图框架.h"
#include "底层绘图/intern/Vulkan/线管/线管.h"

#include "core/shader_ray.h"

using namespace std;






S_Mesh操作::S_Mesh操作(S_Surface * s)
	:m_Mesh(s)
{

}

void S_Mesh操作::f_重置网格(S_Surface * s) {

}

void S_Mesh操作::f_Add(const S_Mesh操作 * mesh, const Mat44f * mat) {
	
}

void S_Mesh操作::f_fill网格(const vector<vec3> xyz, const vector<vec3> normal, const vector<uvec4_8> color, const vector<uint32> index, const vector<vec2> texcoord, uint8 纹理坐标层数)
{
	void* ctx = 0;

	switch (f_get后端框架名称()) {
	case E_绘图API::E_DirectX12:
		ctx = f_get环境();
		break;
	default:
		break;
	} ;

}

void S_Mesh操作::f_add顶点(const vec3& xyz, const vec3& normal, const uvec4_8& color, const vec2* texcoord, uint8 纹理坐标层数)
{

}

/*void S_Mesh操作::f_add三角形(const vector<ivec3> index, uint32 iNum)
{
	//f_resize_vector_GL缓存(&m_Mesh->m_顶点数据.m_索引, iNum*3);
	f_填充GL缓存数据(index, m_Mesh->m_顶点数据.m_索引, E_GPU缓存类型::e_INDEX);
}*/

void S_Mesh操作::f_add三角形(const ivec3 & index)
{

}







void S_Mesh_CUDA::f_AddMesh(const S_Mesh& m) {
	//auto& mesh = *dynamic_cast<const S_Mesh_CUDA*>(&m);
	uint32_t offset = uint32_t(m_positions.size());

	std::vector<vec3> vert;
	m.f_get顶点(vert);
	std::vector<uint32> index;
	m.f_get索引(index);
	std::vector<vec3> normal;
	m.f_get法线(normal);
	std::vector<vec4> color;
	m.f_get颜色(color);


	// add new vertices
	//m_positions.insert(m_positions.end(), vert.begin(), vert.end());
	//m_normals.insert(m_normals.end(), normal.begin(), normal.end());
	//m_colours.insert(m_colours.end(), color.begin(), color.end());
	uint32 num = vert.size();
	m_positions.reserve(m_positions.size() + num);
	for (uint32 i = 0; i < num; ++i) {
		vec3 v = vert[i];
		m_positions.push_back({ v.x, v.y, v.z });
	}

	num = normal.size();
	m_normals.reserve(m_normals.size() + num);
	for (uint32 i = 0; i < num; ++i) {
		vec3 v = normal[i];
		m_normals.push_back({ v.x, v.y, v.z });
	}

	num = color.size();
	m_normals.reserve(m_normals.size() + num);
	for (uint32 i = 0; i < num; ++i) {
		vec4 v = color[i];
		m_colours.push_back({ v.x, v.y, v.z, v.w });
	}


	// add new indices with offset
	for (uint32_t i = 0; i < index.size(); ++i) {
		m_indices.push_back(index[i] + offset);
	}
}







void S_Mesh_CUDA::f_get顶点(S_结构对象指针 data) { 
	std::vector<vec3>& v = *((std::vector<vec3>*)data);

	uint32 num = m_positions.size();
	v.resize(num);

	auto* p = m_positions.data();
	auto* r = v.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}

void S_Mesh_CUDA::f_get法线(S_结构对象指针 data) { 
	std::vector<vec3>& v = *((std::vector<vec3>*)data);

	uint32 num = m_normals.size();
	v.resize(num);

	auto* p = m_normals.data();
	auto* r = v.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}

void S_Mesh_CUDA::f_get索引(S_结构对象指针 data) { 
	std::vector<uint32>& v = *((std::vector<uint32>*)data);

	uint32 num = m_indices.size();
	v.resize(num);

	auto* p = m_indices.data();
	auto* r = v.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = p[i];
	});

}





void S_Mesh_CUDA::f_fill顶点(const std::vector<vec3>& xyz) {
	uint32 num = xyz.size();
	m_positions.resize(num);

	auto* p = xyz.data();
	auto* r = m_positions.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}

void S_Mesh_CUDA::f_fill法线(const std::vector<vec3>& normal) {
	uint32 num = normal.size();
	m_normals.resize(num);

	auto* p = normal.data();
	auto* r = m_normals.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { p[i].x, p[i].y, p[i].z };
	});
}

void S_Mesh_CUDA::f_fill索引(const std::vector<uint32>& index) {
	//m_indices = index;
	uint32 num = index.size();
	m_indices.resize(num);

	auto* p = index.data();
	auto* r = m_indices.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = p[i];
	});
}

void S_Mesh_CUDA::f_fill颜色(const std::vector<uvec4_8>& color) {
	uint32 num = color.size();
	m_colours.resize(num);

	auto* p = color.data();
	auto* r = m_colours.data();
	Concurrency::parallel_for<uint32>(0, num, [&](uint32 i) {
		r[i] = { float32(p[i].x / 255), float32(p[i].y / 255), float32(p[i].z / 255), float32(p[i].w / 255) };
	});
}

void S_Mesh_CUDA::f_fillUV(const std::vector<vec2>& texcoord, uint8 纹理层) {

}




void S_Mesh_CUDA::f_fill顶点(const vec3* xyz, uint32 num) {

}

void S_Mesh_CUDA::f_fill法线(const vec3* normal, uint32 num) {

}

/*void S_Mesh_CUDA::f_fill索引(const uint32* index, uint32 num) {

}*/

void S_Mesh_CUDA::f_fillUV(const vec2* index, uint32 num) {

}









void S_Mesh_CUDA::f_DuplicateVertex(uint32_t i){
	assert(m_positions.size() > i);
	m_positions.push_back(m_positions[i]);

	if (m_normals.size() > i)
		m_normals.push_back(m_normals[i]);

	if (m_colours.size() > i)
		m_colours.push_back(m_colours[i]);

	if (m_texcoords[0].size() > i)
		m_texcoords[0].push_back(m_texcoords[0][i]);

	if (m_texcoords[1].size() > i)
		m_texcoords[1].push_back(m_texcoords[1][i]);
}

void S_Mesh_CUDA::f_CalculateNormals()
{
}

void S_Mesh_CUDA::f_Normalize(float32 s) {
	/*
	Vec3 lower, upper;
	GetBounds(lower, upper);
	Vec3 edges = upper - lower;

	Transform(TranslationMatrix(Point3(-lower)));

	float maxEdge = max(edges.x, max(edges.y, edges.z));
	Transform(ScaleMatrix(s / maxEdge));
	*/
}

void S_Mesh_CUDA::f_getBounds(Vec3 & outMinExtents, Vec3 & outMaxExtents) const {
	Point3 minExtents(FLT_MAX);
	Point3 maxExtents(-FLT_MAX);

	// calculate face bounds
	for (uint32_t i = 0; i < m_positions.size(); ++i) {
		const Point3& a = m_positions[i];

		minExtents = Min(a, minExtents);
		maxExtents = Max(a, maxExtents);
	}

	outMinExtents = Vec3(minExtents);
	outMaxExtents = Vec3(maxExtents);
}























uint32 S_Mesh操作::f_get顶点数量() {
	//return m_Mesh->m_顶点缓存->m_顶点->m_Count;
	return 0;
}

const vec3 * S_Mesh操作::f_get顶点() {
	//return ((const vec3*)(m_Mesh->m_顶点缓存->f_get顶点().BufferLocation));
	return 0;
}

vec3 * S_Mesh操作::f_Map顶点() {
	//return ((vec3*)(m_Mesh->m_顶点缓存->f_get顶点().BufferLocation));
	return 0;
}

void S_Mesh操作::f_UnMap_顶点() {
	//m_Mesh->m_顶点缓存->f_UpMap顶点();
}







uint32 S_Mesh操作::f_get索引数量() {
	//return m_Mesh->m_顶点缓存->m_索引->m_Count;
	return 0;
}

const uint32* S_Mesh操作::f_get索引() {
	//return (const uint32*)(m_Mesh->m_顶点缓存->f_get索引().BufferLocation);
	return 0;
}

uint32* S_Mesh操作::f_Map索引() {
	//return (uint32*)(m_Mesh->m_顶点缓存->f_get索引().BufferLocation);
	return 0;
}

void S_Mesh操作::f_UnMap_索引() {
	//m_Mesh->m_顶点缓存->f_UpMap索引();
}



















S_VKMesh板载缓存::S_VKMesh板载缓存(S_设备环境& ctx) {
	m_Ctx     = ctx;
	m_Tye     = E_网格数据枚举::e_Mesh_VULKAN;
	m_VertNum = 0;
	m_间接    = 0;
	
	uint32 Flags = E_板载缓存类型::e_SSBO | E_板载缓存类型::e_光追BVH | E_板载缓存类型::e_着色端内存地址;

	static S_板载缓存* g_UV = f_buf_create板载缓存(ctx, E_板载缓存类型::e_SSBO, E_板载缓存类型::e_SSBO | Flags, sizeof(vec2), 1);
	m_UV = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	*m_UV = f_buf_alloc(g_UV, 1);

	static S_板载缓存* g_UV索引 = f_buf_create板载缓存(ctx, E_板载缓存类型::e_SSBO, E_板载缓存类型::e_SSBO | Flags, sizeof(uvec3), 1);
	m_UV索引 = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	*m_UV索引 = f_buf_alloc(g_UV索引, 0);

	//static S_板载缓存* g_顶点 = f_buf_create板载缓存(ctx, E_板载缓存类型::e_VBO, E_板载缓存类型::e_VBO | Flags, sizeof(vec3), 0);
	m_顶点 = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	*m_顶点 = f_buf_alloc(S_Mesh::g_顶点v, 0);

	m_索引 = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	*m_索引 = f_buf_alloc(S_Mesh::g_索引, 0);

	m_材质槽ID = (S_UI32Array*)f_core_array_new(1, sizeof(uint32));
	m_材质槽ID->ptr_userData[0] = 0;

	m_面 = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	*m_面 = f_buf_alloc(S_Mesh::g_面, 0);


	m_网格元素属性 = f_buf_alloc(S_Mesh::g_网格属性, 1);


	m_底层光追加速结构 = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	*m_底层光追加速结构 = f_buf_alloc(S_Mesh::g_BLAS, 0);


	//m_权重 = f_create板载缓存(ctx, sizeof(float32));
	//m_间接 = f_create板载缓存(ctx, sizeof(float32));
	m_骨骼属性 = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	(*m_骨骼属性) = f_buf_alloc(S_Mesh::g_骨骼属性, 0);

	m_骨骼权重 = (S_GPU内存块索引*)malloc(sizeof(S_GPU内存块索引));
	(*m_骨骼权重) = f_buf_alloc(S_Mesh::g_骨骼权重, 0);
	//m_顶点对应骨骼ID = f_buf_create板载缓存(ctx, E_板载缓存类型::e_SSBO, Flags, sizeof(uint32), 1);


	m_顶点配置Flags = (uint32*)malloc(sizeof(uint32));
	(*m_顶点配置Flags) = 0;


	m_光追加速结构 = 0;
}

S_VKMesh板载缓存::S_VKMesh板载缓存(S_VKMesh板载缓存* p) {
	m_VertNum = 0;
	m_Ctx            = p->m_Ctx;
	m_GPU参数布局    = {};
	m_顶点配置Flags  = p->m_顶点配置Flags;

	m_顶点   = p->m_顶点;
	m_索引   = p->m_索引;
	m_UV     = p->m_UV;
	m_UV索引 = p->m_UV索引;

	m_材质槽ID = p->m_材质槽ID;


	m_骨骼属性 = p->m_骨骼属性;
	m_骨骼权重 = p->m_骨骼权重;
	//m_顶点对应骨骼ID = p->m_顶点对应骨骼ID;

	m_底层光追加速结构 = p->m_底层光追加速结构;

	m_面             = p->m_面;
	

	m_网格元素属性 = f_buf_alloc(S_Mesh::g_网格属性, 1);

	m_间接     = nullptr;
	m_是否链接 = true;

	m_Material = p->m_Material;
	if (m_Material && m_Material->mf_GPU材质槽更新) {
		m_Material->mf_GPU材质槽更新(m_Material, m_GPU参数布局, 2);
	}

	m_光追加速结构 = 0;
}

S_VKMesh板载缓存::S_VKMesh板载缓存() {
	m_Ctx = {};
	m_VertNum = 0;

	if (m_间接) {
		f_buf_erase(*m_间接);
	}

	m_光追加速结构 = 0;
}

S_VKMesh板载缓存::~S_VKMesh板载缓存() {
	if (m_是否链接) {

	}
	else {
		//f_buf_release板载缓存(m_蒙皮权重);
		//f_buf_release板载缓存(m_顶点对应骨骼ID);

		free(m_顶点配置Flags);
		

		f_buf_erase(*m_顶点);
		f_buf_erase(*m_索引);
		f_buf_erase(*m_UV索引);
		f_buf_erase(*m_UV);
		f_buf_erase(*m_面);
		

		f_buf_erase(*m_骨骼属性);
		f_buf_erase(*m_骨骼权重);
		
		f_buf_erase(*m_底层光追加速结构);

		
		free(m_顶点);
		free(m_索引);
		free(m_UV索引);
		free(m_UV);
		free(m_面);

		free(m_骨骼属性);
		free(m_骨骼权重);

		free(m_底层光追加速结构);


		f_core_array_free((S_Array*)m_材质槽ID);
	}

	if (m_间接) {
		f_buf_erase(*m_间接);
	}
	

	f_buf_erase(m_网格元素属性);
	if(m_绘制属性) free(m_绘制属性);

	if (m_GPU参数布局.m_参数数量) {
		f_release缓存槽(&m_GPU参数布局);
	}
}

void S_VKMesh板载缓存::f_拷贝实例(const S_Mesh* mesh) {
	const S_VKMesh板载缓存* p = dynamic_cast<const S_VKMesh板载缓存*>(mesh);

	m_Ctx     = p->m_Ctx;
	m_VertNum = p->m_VertNum;

	m_顶点 = p->m_顶点;
	m_索引 = p->m_索引;
	m_间接 = p->m_间接;

	m_材质槽ID = p->m_材质槽ID;
	m_骨骼属性 = p->m_骨骼属性;
	m_骨骼权重 = p->m_骨骼权重;

	m_底层光追加速结构 = p->m_底层光追加速结构;
	

	m_UV = p->m_UV;
	m_UV索引 = p->m_UV索引;

	m_Material = p->m_Material;
	m_网格元素属性 = p->m_网格元素属性;
}

void S_VKMesh板载缓存::f_fill顶点(const vec3* xyz, uint32 num) {
	if (!num) {
		f_buf_gresize(*m_顶点, 0);
		return;
	}
	
	switch (*m_顶点配置Flags) {
	case 0:
	case E_顶点组合标志::e_坐标: {
		f_buf_gresize(*m_顶点, num);
		vec3* v = f_buf_Vec3_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			v[i] = xyz[i];
		};
		break;
	}
	
	case E_顶点组合标志::e_坐标_法线: {
		f_buf_gresize(*m_顶点, num);
		S_VN* vn = f_buf_VN_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			vn[i].vert = xyz[i];
		};
		break;
	}
	
	case E_顶点组合标志::e_坐标_颜色: {
		f_buf_gresize(*m_顶点, num);
		S_VC* vc = f_buf_VC_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			vc[i].vert = xyz[i];
		};
		break;
	}

	case E_顶点组合标志::e_坐标_法线_UV: {
		f_buf_gresize(*m_顶点, num);
		S_VNT1* vnt = f_buf_VNT_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			vnt[i].vert = xyz[i];
		};
		break;
	}
	}
}

void S_VKMesh板载缓存::f_fill法线(const vec3* normal, uint32 num) {
	//f_buf_resize(m_顶点, num, E_板载缓存类型::e_VBO);
	

	//m_顶点->f_map();
	switch (*m_顶点配置Flags) {
	case E_顶点组合标志::e_坐标_法线: {
		//S_VN* data = (S_VN*)(m_顶点->m_mappedPtr);
		f_buf_gresize(*m_顶点, num);
		S_VN* data = f_buf_VN_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i].normal = normal[i];
		};
	}
	break;

	case E_顶点组合标志::e_坐标_法线_UV: {
		//S_VNT1* data = (S_VNT1*)(m_顶点->m_mappedPtr);
		f_buf_gresize(*m_顶点, num);
		S_VNT1* data = f_buf_VNT_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i].normal = normal[i];
		};
	}
	break;

	default:
		break;
	}
	//m_顶点->f_unmap();
}

void S_VKMesh板载缓存::f_fillUV(const vec2* uv, uint32 num, uint8 纹理层) {
	//f_buf_resize(m_顶点, num, E_板载缓存类型::e_VBO);
	
	//m_顶点->f_map();
	switch (*m_顶点配置Flags) {
	case E_顶点组合标志::e_坐标_法线_UV: {
		//S_VNT1* data = (S_VNT1*)(m_顶点->m_mappedPtr);
		f_buf_gresize(*m_顶点, num);
		S_VNT1* data = f_buf_VNT_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i].UV = uv[i];
		};
		break;
	}
	}

	//m_顶点->f_unmap();

}

void S_VKMesh板载缓存::f_fill颜色(const std::vector<S_RGBA8UI>& c) {
	uint32 num = c.size();
	//f_buf_resize(m_顶点, num, E_板载缓存类型::e_VBO);
	
	auto* p = c.data();
	//m_顶点->f_map();
	switch (*m_顶点配置Flags){
	case E_顶点组合标志::e_坐标_颜色: {
		//S_VC* data = (S_VC*)(m_顶点->m_mappedPtr);
		f_buf_gresize(*m_顶点, num);
		S_VC* data = f_buf_VC_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i].color = f_PackData4X8(p[i]);
		};
		break;
	}
		
	}

	//m_顶点->f_unmap();
}

/*void S_VKMesh板载缓存::f_fill索引(const std::vector<uint32>& index) {
	f_fill板载缓存(m_索引, index, E_板载缓存类型::e_INDEX, m_Ctx);
	f_buf_resize板载缓存(m_材质ID, index.size());
	f_buf_fill(m_材质ID, 0);
}*/

void S_VKMesh板载缓存::f_fillUV(const std::vector<vec2>& uv1, uint8 纹理层) {
}

void S_VKMesh板载缓存::f_fill权重(const float32* w, uint32 num) {
	//m_顶点配置Flags |= E_顶点标志位::e_顶点权重;
	//f_buf_fill板载缓存(m_蒙皮权重, w, num);
}

void S_VKMesh板载缓存::f_fill骨骼ID(const uint32* bid, uint32 num) {
	//m_顶点配置Flags |= E_顶点标志位::e_顶点权重;
	//f_buf_fill板载缓存(m_顶点对应骨骼ID, bid, num);
}

void S_VKMesh板载缓存::f_fill骨骼属性(const S_骨骼属性& 骨骼属性) {
	//f_buf_fill板载缓存(m_骨骼属性, &骨骼属性, 1);
}



void S_VKMesh板载缓存::f_填充顶点数据(const std::vector<S_VN>& data) {
	*m_顶点配置Flags |= E_顶点标志位::e_顶点法线;
	f_buf_erase(*m_顶点);

	*m_顶点 = f_buf_alloc(g_顶点vn, data.size());
	f_gbuf_fill(*m_顶点, data.data(), 0, data.size());
	//f_buf_fill板载缓存(m_顶点, data, E_板载缓存类型::e_VBO);
}

void S_VKMesh板载缓存::f_填充顶点数据(const std::vector<S_VC>& data) {
	*m_顶点配置Flags |= E_顶点标志位::e_顶点颜色;
	if(data.size()) {
		f_buf_erase(*m_顶点);
		*m_顶点 = f_buf_alloc(g_顶点vc, data.size());

		f_gbuf_fill(*m_顶点, data.data(), 0, data.size());
		//f_buf_fill板载缓存(m_顶点, data, E_板载缓存类型::e_VBO);
	}
	else f_Clear();
}

uint32 S_VKMesh板载缓存::f_填充顶点数据(uint16 bitSize, uint64 num, void* data) {
	if(m_顶点->m_Buf) f_buf_erase(*m_顶点);
	uint32 sid = 0;

	if(num) {
		switch (*m_顶点配置Flags) {
			case E_顶点组合标志::e_坐标_法线_UV:
				*m_顶点 = f_buf_alloc(g_顶点vnt, num);
				break;
			case E_顶点组合标志::e_坐标_法线:
				*m_顶点 = f_buf_alloc(g_顶点vn, num);
				break;
			case E_顶点组合标志::e_坐标_颜色:
				*m_顶点 = f_buf_alloc(g_顶点vc, num);
				break;
			case E_顶点标志位::e_顶点坐标:
				*m_顶点 = f_buf_alloc(g_顶点v, num);
				break;
		}

		sid = m_顶点->m_Mem.m_偏移;
		f_gbuf_fill(*m_顶点, data, 0, num);
	}
	else {
		f_Clear();
	}
	return sid;
}

uint32 S_VKMesh板载缓存::f_填充索引数据(uint16 bitSize, uint64 num, void* data) {
	switch (bitSize) {
	case 4:
		f_buf_gresize(*m_面, num/3);
		break;
	case 12:
		f_buf_gresize(*m_面, num);

		num *= 3;
		break;
	case 16:
		break;
	default:
		break;
	}
	f_buf_gresize(*m_索引, num);
	f_gbuf_fill(*m_索引, data, 0, num);
	
	S_FaceElement* fe = f_buf_面元素_ptr(*m_面);
	for (uint32 i = 0; i < m_面->m_Mem.m_大小; ++i) {
		fe[i].MaterialID = 0;
		fe[i].FacesMooth = 0;
		fe[i].ObType = DEF_OBTYPE_Mesh;
	}
	return 0;
}

uint32 S_VKMesh板载缓存::f_fillUV索引数据(uint16 bitSize, uint32 num, const void* data) {
	bitSize /= 4;
	f_gbuf_fill(*m_UV索引, data, 0, num * bitSize);
	return m_UV索引->m_Mem.m_偏移;
}

void S_VKMesh板载缓存::f_重置顶点数量(uint64 num) {
	f_buf_gresize(*m_顶点, num);
}

void S_VKMesh板载缓存::f_Clear() {
	//m_顶点->m_Size = 0;
	f_buf_gresize(*m_顶点, 0);
}

void S_VKMesh板载缓存::f_Clear索引() {
	f_buf_erase(*m_索引);
	//m_索引->m_Size = 0;
}




void S_VKMesh板载缓存::f_get顶点(std::vector<vec3>& vert) const {
	uint32 num = m_顶点->m_Mem.m_大小;
	vert.resize(num);
	auto* data = vert.data();

	switch (*m_顶点配置Flags) {
	case E_顶点组合标志::e_坐标: {
		vec3* xyz = f_buf_Vec3_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i] = xyz[i];
		};

		break;
	}
		
	case E_顶点组合标志::e_坐标_UV: {
		break;
	}

	case E_顶点组合标志::e_坐标_权重: {
		break;
	}

	case E_顶点组合标志::e_坐标_法线: {
		S_VN* xyz = f_buf_VN_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i] = xyz[i].vert;
		};

		break;
	}

	case E_顶点组合标志::e_坐标_法线_UV: {
		break;
	}

	case E_顶点组合标志::e_坐标_法线_UV_颜色: {
		break;
	}

	case E_顶点组合标志::e_坐标_颜色: {
		break;
	}

	}
}

void S_VKMesh板载缓存::f_get法线(std::vector<vec3>& normal) const {
	uint32 num = m_顶点->m_Mem.m_大小;
	normal.resize(num);
	//normal.resize(m_顶点->m_Size);

	auto* data = normal.data();

	switch (*m_顶点配置Flags) {
	case E_顶点组合标志::e_坐标: {
		
		break;
	}

	case E_顶点组合标志::e_坐标_UV: {

		break;
	}

	case E_顶点组合标志::e_坐标_权重: {

		break;
	}

	case E_顶点组合标志::e_坐标_法线: {
		S_VN* xyz = f_buf_VN_ptr(*m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			data[i] = xyz[i].vert;
		};
		break;
	}

	case E_顶点组合标志::e_坐标_法线_UV: {

		break;
	}

	case E_顶点组合标志::e_坐标_法线_UV_颜色: {

		break;
	}

	case E_顶点组合标志::e_坐标_颜色: {

		break;
	}

	}
}

void S_VKMesh板载缓存::f_get索引(std::vector<uint32>& index) const {
	index.resize(m_索引->m_Mem.m_大小);
	memcpy(index.data(), f_buf_UI32_ptr(*m_索引), sizeof(uint32) * m_索引->m_Mem.m_大小);
}

void S_VKMesh板载缓存::f_get颜色(std::vector<vec4>& index) const {
}

uint32 S_VKMesh板载缓存::f_get顶点数量() {
	//if(m_顶点) return m_顶点->m_Size;
	return m_顶点->m_Mem.m_大小;
}

uint32 S_VKMesh板载缓存::f_get索引数量() {
	if (m_索引) return m_索引->m_Mem.m_大小;
	return 0;
}

void S_VKMesh板载缓存::f_绘制(S_渲染参数& 渲染参数) {
	渲染参数.m_线宽 = m_线宽;
	//渲染参数.m_实例偏移 = 0;
	//渲染参数.m_实例数量 = 渲染参数.m_实例数量;
	//渲染参数.m_顶点数量 = m_顶点->m_Size;
	渲染参数.m_顶点内存偏移 = m_顶点->m_Mem.m_偏移;
	渲染参数.m_顶点数量 = m_顶点->m_Mem.m_大小;
	
	if (m_绘制属性) {
		S_Vk着色* shader = static_cast<S_Vk着色*>(m_Material->m_Shader);
		S_绘图设备配置* info = f_vk_get绘图环境(m_Ctx);

		(*m_绘制属性).MeshPropOffset = m_网格元素属性.m_Mem.m_偏移;
		(*m_绘制属性).BonesOffset = (*m_骨骼属性).m_Mem.m_偏移;

		vkCmdPushConstants(info->m_命令缓存, 
			               shader->m_线管布局, 
						   VK_SHADER_STAGE_VERTEX_BIT,
						   0, 
						   sizeof(S_MeshDrawProp), 
						   m_绘制属性);
	}
	
	//auto 属性 = f_buf_物体变换属性_at(m_网格元素属性);

	if (m_索引->m_Mem.m_大小) {
		S_索引渲染参数 索引参数;
		
		索引参数.m_索引 = m_索引->m_Buf;
		索引参数.m_间接 = 0;
		索引参数.m_索引数量 = m_索引->m_Mem.m_大小;
		索引参数.m_实例数量 = 渲染参数.m_实例数量;
		渲染参数.m_间接绘制 = nullptr;
		渲染参数.m_索引内存偏移 = m_索引->m_Mem.m_偏移;
		渲染参数.m_索引内存数量 = m_索引->m_Mem.m_大小;
		
		
		f_Draw_索引三角形(m_Ctx, m_Material, m_顶点->m_Buf, 索引参数, 渲染参数);
	}
	else if(m_顶点->m_Mem.m_大小) {
		if (m_间接) {
			//渲染参数.m_间接绘制 = m_间接->m_Buf;
			渲染参数.m_间接 = m_间接;
			f_Draw_间接序列(m_Ctx, m_Material, m_顶点->m_Buf, 渲染参数);
		}
		else {
			f_Draw_序列(m_Ctx, m_Material, m_顶点->m_Buf, 渲染参数);
		}
	}
}







void S_Mesh_CPU::f_AddMesh(const S_Mesh& m) {
}
void S_Mesh_CPU::f_fill顶点(const std::vector<vec3>& xyz) {
}
void S_Mesh_CPU::f_fill法线(const std::vector<vec3>& normal) {
}
void S_Mesh_CPU::f_fill索引(const std::vector<uint32>& index) {
}
void S_Mesh_CPU::f_fill颜色(const std::vector<uvec4_8>& color) {
}
void S_Mesh_CPU::f_fillUV(const std::vector<vec2>& texcoord, uint8 纹理层) {
}
void S_Mesh_CPU::f_fill顶点(const vec3* xyz, uint32 num) {
}
void S_Mesh_CPU::f_fill法线(const vec3* normal, uint32 num) {
}
void S_Mesh_CPU::f_fillUV(const vec2* index, uint32 num) {
}

void S_Mesh_CPU::f_填充顶点数据(const std::vector<S_VN>& data) {
	uint32 num = data.size();
	auto* vn = data.data();

	m_positions.resize(num*2);
	//m_normals.resize(num);
	for (uint32 i = 0; i < num; ++i) {
		m_positions[i*2] = vn[i].vert;
		m_positions[i*2+1] = vn[i].normal;
		//m_normals[i] = vn[i].normal;
	}
}

void S_Mesh_CPU::f_填充顶点数据(const std::vector<S_VC>& data) {

}

uint32 S_Mesh_CPU::f_填充顶点数据(uint16 bitSize, uint64 num, void* data) {
	m_positions.resize(num);
	memcpy(m_positions.data(), data, num * bitSize);
	return 0;
}

uint32 S_Mesh_CPU::f_填充索引数据(uint16 bitSize, uint64 num, void* data) {
	switch (bitSize)
	{
		case sizeof(uint32) :
			m_indices.resize(num);
			break;

			case sizeof(uvec3):
				m_indices.resize(num * 3);
				break;
	default:
		break;
	}
	
	memcpy(m_indices.data(), data, num * bitSize);
	return 0;
}

void S_Mesh_CPU::f_get顶点(std::vector<vec3>& vert) const {
	vert = m_positions;
}

void S_Mesh_CPU::f_get法线(std::vector<vec3>& normal) const {
	normal = m_normals;
}

void S_Mesh_CPU::f_get索引(std::vector<uint32>& index) const {
	index = m_indices;
}

void S_Mesh_CPU::f_get颜色(std::vector<vec4>& index) const {

}

void S_Mesh_CPU::f_Clear() {
	m_positions.clear();
}

void S_Mesh_CPU::f_Clear索引() {
	m_indices.clear();
}

void S_Mesh_CPU::f_getBounds(Vec3& minExtents, Vec3& maxExtents) const
{
}






Inline vec3 f_surface_从面计算法线(const vec3& v0, const vec3& v1, const vec3& v2) {
	vec3 e0 = (v1 - v0);
	vec3 e1 = (v2 - v0);
	return (vec_cross(e0, e1));

	//vec3 e0 = vec_normalize2(v1 - v0);
	//vec3 e1 = vec_normalize2(v2 - v0);
	//return vec_normalize2(vec_cross(e0, e1));
}

template<typename T>
void f_计算网格三角形法线(S_点距八叉树* t, T* p顶点, uvec3* p索引, int32 num) {
#pragma omp parallel for
	for (int32 i = 0; i < num; ++i) {
		std::vector<void*> 面索引_空间数据;

		f_空间划分_get位置子集数据(t, p顶点[i].vert, 面索引_空间数据);

		vec3 法线 = {};
		void** 面索引_空间数据_ptr = 面索引_空间数据.data();
		uint32 面索引_空间数据数量 = 面索引_空间数据.size();

		for (uint32 空间数据_i = 0; 空间数据_i < 面索引_空间数据数量; ++空间数据_i) {
			auto* 面索引组 = (*((std::vector<uint32>*)面索引_空间数据_ptr[空间数据_i])).data();
			uint32 面索数量 = (*((std::vector<uint32>*)面索引_空间数据_ptr[空间数据_i])).size();
			for (uint32 index = 0; index < 面索数量; ++index) {
				uvec3 trangle = p索引[面索引组[index]];
				if (trangle.x == i || trangle.y == i || trangle.z == i) {
					法线 += f_surface_从面计算法线(p顶点[trangle.x].vert, p顶点[trangle.y].vert, p顶点[trangle.z].vert);
				}
			}
		}

		p顶点[i].normal = vec_normalize(法线);
	}
}

void f_surface_计算三角形球体包围盒(S_Mesh* mesh, std::vector<S_VecSphere>& 包围盒) {
	//auto 索引 = mesh->f_map索引();
	auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);

	uint32 num = mesh->m_索引->m_Mem.m_大小 / 3;
	//vec3* p顶点 = (vec3*)顶点.point;

	包围盒.resize(num);
	auto* bounds_ptr = 包围盒.data();


	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线 || *mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_颜色) {
		S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			uvec3 index = p索引[i];
			auto q = f_graph_取三角形球形包围(vn[index.x].vert, vn[index.y].vert, vn[index.z].vert);
			bounds_ptr[i] = q;
		}
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线_UV) {
		//S_VNT1* vn = (S_VNT1*)顶点.point;
		S_VNT1* vn = f_buf_VNT_ptr(*mesh->m_顶点);
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			uvec3 index = p索引[i];
			auto q = f_graph_取三角形球形包围(vn[index.x].vert, vn[index.y].vert, vn[index.z].vert);
			bounds_ptr[i] = q;
		}
	}
	else {
		vec3* p顶点 = f_buf_Vec3_ptr(*mesh->m_顶点);
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			uvec3 index = p索引[i];
			auto q = f_graph_取三角形球形包围(p顶点[index.x], p顶点[index.y], p顶点[index.z]);
			bounds_ptr[i] = q;
		}
	}

	//mesh->f_unmap索引();
}


void f_surface_计算面平滑法线(S_Mesh* mesh, S_点距八叉树* t) {
	std::vector<S_VecSphere> 包围盒;

	f_surface_计算三角形球体包围盒(mesh, 包围盒);
	f_空间划分_从包围盒构建子集(t, 包围盒);

	auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);
	//auto 索引 = mesh->f_map索引();

	//uint32 num   = 索引.count / 3;
	//uint32 num   = 顶点.count;
	uint32 num   = mesh->m_顶点->m_Mem.m_大小;
	//uvec3* p索引 = (uvec3*)索引.point;
	

	switch (*mesh->m_顶点配置Flags) {
	case E_顶点组合标志::e_坐标_法线_UV: {
		//S_VNT1* p顶点 = (S_VNT1*)顶点.point;
		S_VNT1* vn = f_buf_VNT_ptr(*mesh->m_顶点);
		f_计算网格三角形法线(t, vn, p索引, num);
		break;
	}
	case E_顶点组合标志::e_坐标_法线: {
		//S_VN* p顶点 = (S_VN*)顶点.point;
		S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
		f_计算网格三角形法线(t, vn, p索引, num);
		break;
	}
	default:
		break;
	}

	//mesh->f_unmap索引();
}






S_面拾取 f_surface_射线面相交(S_Mesh* mesh, const Mat44f mat[2], const S_MeshTranformProp& 间接属性, const uvec2& Offset_num, const vec3& s, const vec3& dir) {
	auto 顶点指针 = mesh->m_顶点->m_Buf->m_mappedPtr;
	vec3 scale = {间接属性.m_XScale, 间接属性.m_YScale, 间接属性.m_ZScale};


	uint32 num = Offset_num.y / 3;
	//vec3    最小相交坐标 = {};
	S_面拾取 拾取信息 = {{}, 100000000, -1};
	vec3     相交坐标 = {};


	bool 是否相交 = false;
	int32 相交情况 = 0;
	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线) {
		S_VN* vn = (S_VN*)顶点指针;
		//S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3;

			uint32 index = i*3 + Offset_num.x;
			v1 = mat[1] * (vn[index    ].vert * 间接属性.m_Scale);
			v2 = mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
			v3 = mat[1] * (vn[index + 2].vert * 间接属性.m_Scale);

			v1 = mat[0] * v1;

			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交距离) {
					拾取信息.相交距离 = 距离;
					拾取信息.面索引 = i;
					//最小相交坐标 = 相交坐标;
					是否相交 = true;
				}
			}
		}
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线_UV) {
		S_VNT1* vn = (S_VNT1*)顶点指针;
		//S_VNT1* vn = f_buf_VNT_ptr(*mesh->m_顶点);

		//#pragma omp parallel for num_threads(线程数)
		for (int32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3;

			uint32 index = i*3 + Offset_num.x;
			v1 = mat[0] * (vn[index    ].vert * 间接属性.m_Scale);
			v2 = mat[0] * (vn[index + 1].vert * 间接属性.m_Scale);
			v3 = mat[0] * (vn[index + 2].vert * 间接属性.m_Scale);


			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交距离) {
					拾取信息.相交距离 = 距离;
					拾取信息.面索引 = i;
					//最小相交坐标 = 相交坐标;
					是否相交 = true;
				}
			}
		}
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_颜色) {
		S_VC* vn = (S_VC*)顶点指针;
		//S_VC* vn = f_buf_VC_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3 = {间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove};
			v1 = v2 = v3;

			uint32 index = i*3 + Offset_num.x;
			switch (间接属性.m_TransformMode) {
			case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
				v1 += mat[1] * (vn[index    ].vert * 间接属性.m_Scale);
				v2 += mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
				v3 += mat[1] * (vn[index + 2].vert * 间接属性.m_Scale);
				break;
			}

			default:
				v1 += (vn[index    ].vert * 间接属性.m_Scale);
				v2 += (vn[index + 1].vert * 间接属性.m_Scale);
				v3 += (vn[index + 2].vert * 间接属性.m_Scale);
				break;
			}

			v1 = mat[0] * v1;
			v2 = mat[0] * v2;
			v3 = mat[0] * v3;


			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交距离) {
					拾取信息.相交距离 = 距离;
					拾取信息.面索引 = i;
					//最小相交坐标 = 相交坐标;
					是否相交 = true;
				}
			}
		}
	}
	else {
		vec3* v = (vec3*)顶点指针;
		//vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			uint32 index = i*3;
			vec3 v1 = mat[0] * (v[index    ] * 1);
			vec3 v2 = mat[0] * (v[index + 1] * 1);
			vec3 v3 = mat[0] * (v[index + 2] * 1);
			相交情况 = f_graph_IntersectTriangle(v1, v2, v3, s, dir, &相交坐标);
			if (相交情况) {
				float32 距离 = vec_len(vec_sub(相交坐标, s));
				if (距离 < 拾取信息.相交距离) {
					拾取信息.相交距离 = 距离;
					拾取信息.面索引 = i;
					//最小相交坐标 = 相交坐标;
					是否相交 = true;
				}
			}
		}
	}

	//mesh->f_unmap顶点();

	return 拾取信息;
}


S_线拾取 f_surface_线段相交(S_Mesh* mesh, const Mat44f mat[2], const S_MeshTranformProp& 间接属性, const uvec2& Offset_num, vec3 s, const vec3& dir, float32 最小相交距离) {
	S_线拾取 拾取线 = { 最小相交距离, 1000000000, -1 };
	//uint32 num = mesh->f_get顶点数量() / 2;
	uint32 num = Offset_num.y / 2;
	if (!num) return 拾取线;

	vec3 最近距离顶点 = {};

	auto 顶点指针 = mesh->m_顶点->m_Buf->m_mappedPtr;
	//auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);
	

	vec3 射线长度补偿 = dir * 最小相交距离;
	s -= 射线长度补偿;

	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线) {
		//S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
		S_VN* vn = (S_VN*)(顶点指针);

		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2 = {间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove};
			v1 = v2;

			uint32 index = i * 2 + Offset_num.x;
			switch (间接属性.m_TransformMode) {
			case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
				v1 = mat[1] * (vn[index    ].vert * 间接属性.m_Scale);
				v2 = mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
				break;
			}

			default:
				v1 = (vn[index    ].vert * 间接属性.m_Scale);
				v2 = (vn[index + 1].vert * 间接属性.m_Scale);
				break;
			}
			v1 = mat[0] * v1;
			v2 = mat[0] * v2;

			


			vec3 相交点;
			float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点, 最小相交距离));
			if (两线段距离 < 拾取线.相交距离) {
				拾取线.相交距离 = 两线段距离;
				拾取线.线索引 = i;
				最近距离顶点 = 相交点;
			}
		}

		拾取线.相交点到起点距离 = vec_len(最近距离顶点 - s);
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_颜色) {
		S_VC* vn = (S_VC*)(顶点指针);
		//S_VC* vn = f_buf_VC_ptr(*mesh->m_顶点);
		
		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2 = {间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove};
			v1 = v2;

			uint32 index = i * 2 + Offset_num.x;

			//v1 = f_lineMeshTranform(v1, 物体变换属性, ModelMat, {});
			//v2 = f_lineMeshTranform(v2, 物体变换属性, ModelMat, {});

			
			switch (间接属性.m_TransformMode) {
			case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
				v1 = mat[1] * (vn[index    ].vert * 间接属性.m_Scale);
				v2 = mat[1] * (vn[index + 1].vert * 间接属性.m_Scale);
				break;
			}

			default:
				v1 = (vn[index    ].vert * 间接属性.m_Scale);
				v2 = (vn[index + 1].vert * 间接属性.m_Scale);
				break;
			}
			v1 = mat[0] * v1;
			v2 = mat[0] * v2;

			vec3 相交点;
			float32 两线段距离 = f_graph_两线段距离(v1, v2, s, dir, 相交点, 最小相交距离);
			if (两线段距离 >= 0 && 两线段距离 < 拾取线.相交距离) {
				拾取线.相交距离 = 两线段距离;
				拾取线.线索引 = i;
				最近距离顶点 = 相交点;
			}
		}

		拾取线.相交点到起点距离 = vec_len(最近距离顶点 - s);
	}
	else {
		vec3* v = (vec3*)(顶点指针);
		//vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			uint32 index = i * 2 + Offset_num.x;
			vec3 v1, v2 = {间接属性.m_XMove, 间接属性.m_YMove, 间接属性.m_ZMove};
			v1 = v2;

			switch (间接属性.m_TransformMode) {
			case DEF_MESH_LINE_TRANFORMTYPEMODEL_NBILLBOARD: {
				v1 = mat[1] * (v[index    ] * 间接属性.m_Scale);
				v2 = mat[1] * (v[index + 1] * 间接属性.m_Scale);
				break;
			}

			default:
				v1 = (v[index    ] * 间接属性.m_Scale);
				v2 = (v[index + 1] * 间接属性.m_Scale);
				break;
			}
			v1 = mat[0] * v1;
			v2 = mat[0] * v2;

			vec3 相交点;
			float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点, 最小相交距离));
			if (两线段距离 < 拾取线.相交距离) {
				拾取线.相交距离 = 两线段距离;
				拾取线.线索引 = i;
				最近距离顶点 = 相交点;
			}

		}

		拾取线.相交点到起点距离 = vec_len(最近距离顶点 - s);
	}

	return 拾取线;
}

S_线拾取 f_surface_线段相交(S_Mesh* mesh, const Mat44f& mat, const vec3& s, const vec3& dir, float32& 距离, uint32 实例) {
	S_线拾取 拾取线 = { 距离, 10000000, -1 };
	//uint32 num = mesh->f_get顶点数量() / 2;

	const auto& indirect = f_buf_at_Indirect(*mesh->m_间接, 实例);
	uint32 num = indirect.vertexCount / 2;
	if (!num) return 拾取线;


	vec3 最近距离顶点 = {};
	//auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);
	//auto* 顶点 = mesh->m_顶点->m_Buf->m_mappedPtr;
	//uint32 vertOffset = indirect.firstVertex;
	const auto& 物体变换属性 = f_buf_物体变换属性_at(mesh->m_网格元素属性, 实例);
	


	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线) {
		//S_VN* vn = (S_VN*)顶点;
		S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2;
			uint32 index = i * 2;
			v1 = mat * vn[indirect.firstVertex + index].vert;
			v2 = mat * vn[indirect.firstVertex + index + 1].vert;

			vec3 相交点;
			float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点));
			if (两线段距离 < 拾取线.相交距离) {
				拾取线.相交距离 = 两线段距离;
				拾取线.线索引 = i;
				最近距离顶点 = 相交点;
			}
		}

		距离 = vec_len(最近距离顶点 - s);
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_颜色) {
		//S_VC* vc = f_buf_VC_ptr(*mesh->m_顶点);
		S_VC* vc = (S_VC*)(mesh->m_顶点->m_Buf->m_mappedPtr);

		mat4 ModelMat = *(mat4*)&mat;
		for (uint32 i = 0; i < num; ++i) {
			uint32 index = i * 2;

			vec3 v1 = vc[indirect.firstVertex + index].vert;
			vec3 v2 = vc[indirect.firstVertex + index + 1].vert;

			//vec3 v1 = vc[index].vert;
			//vec3 v2 = vc[index + 1].vert;
			//v1 = f_lineMeshTranform(v1, 物体变换属性, ModelMat, {});
			//v2 = f_lineMeshTranform(v2, 物体变换属性, ModelMat, {});

			v1 = mat * v1;
			v2 = mat * v2;
			
			vec3 相交点;
			float32 两线段距离 = f_graph_两线段距离(v1, v2, s, dir, 相交点); 
			if (两线段距离 >= 0.0f && 两线段距离 < 拾取线.相交距离) {
				拾取线.相交距离 = 两线段距离;
				拾取线.线索引 = i;
				最近距离顶点 = 相交点;
			}
		}

		距离 = vec_len(最近距离顶点 - s);
	}
	else {
		//vec3* v = (vec3*)顶点;
		vec3* v = f_buf_Vec3_ptr(*mesh->m_顶点);
		
		for (uint32 i = 0; i < num; ++i) {
			uvec2 index;
			index.x = i * 2;
			index.y = i * 2 + 1;
			vec3 v1 = mat * v[index.x + indirect.firstVertex];
			vec3 v2 = mat * v[index.y + indirect.firstVertex];


			vec3 相交点;
			float32 两线段距离 = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点));
			if (两线段距离 < 拾取线.相交距离) {
				拾取线.相交距离 = 两线段距离;
				拾取线.线索引 = i;
				最近距离顶点 = 相交点;
			}

		}

		距离 = vec_len(最近距离顶点 - s);
	}

	//mesh->f_unmap索引();
	return 拾取线;
}



bool f_surface_框选线段(S_Mesh* mesh, const Mat44f& mat, const vec4 平面[5]) {
	uint32 num = mesh->m_顶点->m_Mem.m_大小 / 2;
	if (!num) return false;

	vec3 最近距离顶点 = {};
	int32 最近相交ID = -1;
	float32 最近相交距离 = 100000000;
	
	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线) {
		S_VN* vn = f_buf_VN_ptr(*mesh->m_顶点);
		
		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2;
			uint32 index = i * 2;
			v1 = mat * vn[index].vert;
			v2 = mat * vn[index + 1].vert;
	
			vec3 相交点{};
			float32 两线段距离 = 0;
			if (两线段距离 < 最近相交距离) {
				最近相交距离 = 两线段距离;
				最近相交ID = i;
				最近距离顶点 = 相交点;
			}
		}
		//距离 = vec_len(最近距离顶点 - s);
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_颜色) {
		S_VC* vc = f_buf_VC_ptr(*mesh->m_顶点);
		
		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2;
			uint32 index = i * 2;
			v1 = mat * vc[index].vert;
			v2 = mat * vc[index + 1].vert;


			bool 有相交 = true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v1, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v2, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;


			vec3 相交点;
			for (uint32 j = 0; j < 5; ++j) {
				有相交 = true;
				if (f_graph_射线相交平面2(v1, v2, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}
		}
		//距离 = vec_len(最近距离顶点 - s);
	}
	else if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线_UV) {
		S_VNT1* vc = f_buf_VNT_ptr(*mesh->m_顶点);
		//uint32* index = f_buf_UI32_ptr(*mesh->m_索引);
	
		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2;
			uint32 index = i * 2;
			v1 = mat * vc[index].vert;
			v2 = mat * vc[index + 1].vert;
			

			bool 有相交 = true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v1, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v2, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;
			




			vec3 相交点;
			for (uint32 j = 0; j < 5; ++j) {
				有相交 = true;
				if (f_graph_射线相交平面2(v1, v2, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}

		}
		//距离 = vec_len(最近距离顶点 - s);
	}
	else {
		vec3* v = (vec3*)f_buf_Vec3_ptr(*mesh->m_顶点);
	
		for (uint32 i = 0; i < num; ++i) {
			uvec2 index;
			index.x = i * 2;
			index.y = i * 2 + 1;
			vec3 v1 = mat * v[index.x];
			vec3 v2 = mat * v[index.y];
	
	
			vec3 相交点{};
			float32 两线段距离=0;
			if (两线段距离 < 最近相交距离) {
				最近相交距离 = 两线段距离;
				最近相交ID = i;
				最近距离顶点 = 相交点;
			}
		}
	}


	return false;
}


bool f_surface_框选线框(S_Mesh* mesh, const Mat44f& mat, const vec4 平面[5]) {
	uint32 num = mesh->m_索引->m_Mem.m_大小 / 3;
	if (!num) return false;

	vec3 最近距离顶点 = {};
	int32 最近相交ID = -1;
	float32 最近相交距离 = 100000000;
	auto p索引 = (uvec3*)f_buf_UI32_ptr(*mesh->m_索引);

	if (*mesh->m_顶点配置Flags == E_顶点组合标志::e_坐标_法线_UV) {
		S_VNT1* vc = f_buf_VNT_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			vec3 v1, v2, v3;
			uvec3 index = p索引[i];
			v1 = mat * vc[index.x].vert;
			v2 = mat * vc[index.y].vert;
			v3 = mat * vc[index.z].vert;


			bool 有相交 = true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v1, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if(有相交) return true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v2, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;
			for (uint32 j = 0; j < 5; ++j) {
				if (f_graph_点到平面距离(v3, 平面[j]) > 0) {
					有相交 = false;
					continue;
				}
			}
			if (有相交) return true;


			
			vec3 相交点;
			for (uint32 j = 0; j < 5; ++j) {
				有相交 = true;
				if (f_graph_射线相交平面2(v1, v2, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}
			
			
			for (uint32 j = 0; j < 5; ++j) {
				有相交 = false;
				if (f_graph_射线相交平面2(v2, v3, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}


			for (uint32 j = 0; j < 5; ++j) {
				有相交 = false;
				if (f_graph_射线相交平面2(v3, v1, 平面[j], 相交点)) {
					for (uint32 k = 0; k < 5; ++k) {
						if (f_graph_点到平面距离(相交点, 平面[k]) > 0) {
							有相交 = false;
							break;
						}
					}
					if (有相交) return true;
				}
			}
			

			if (最近相交ID >= 0) {
				cout << "线框3 " << 最近相交ID << std::endl;
			}
		}
		//距离 = vec_len(最近距离顶点 - s);
	}
	else {
		vec3* v = (vec3*)f_buf_Vec3_ptr(*mesh->m_顶点);

		for (uint32 i = 0; i < num; ++i) {
			uvec2 index;
			index.x = i * 2;
			index.y = i * 2 + 1;
			vec3 v1 = mat * v[index.x];
			vec3 v2 = mat * v[index.y];


			vec3 相交点{};
			float32 两线段距离 = 0;// = fabs(f_graph_两线段距离(v1, v2, s, dir, 相交点));
			if (两线段距离 < 最近相交距离) {
				最近相交距离 = 两线段距离;
				最近相交ID = i;
				最近距离顶点 = 相交点;
			}
		}
		//距离 = vec_len(最近距离顶点 - s);
	}


	return false;
}

bool f_surface_框选包围盒(S_Mesh* me, const Mat44f& mat, const vec4 平面[5]) {
	vec3 vert[8];
	
	vert[0] = mat * me->m_Bound.min;
	vert[1] = mat * me->m_Bound.max;

	vert[2] = { vert[1].x, vert[0].y, vert[0].z };
	vert[3] = { vert[0].x, vert[1].y, vert[0].z };
	vert[4] = { vert[0].x, vert[0].y, vert[1].z };

	vert[5] = { vert[0].x, vert[1].y, vert[1].z };
	vert[6] = { vert[1].x, vert[0].y, vert[1].z };
	vert[7] = { vert[1].x, vert[1].y, vert[0].z };


	for (uint32 i = 0; i < 8; ++i) {
		bool 有相交 = true;
		for (uint32 k = 0; k < 5; ++k) {
			if (f_graph_点到平面距离(vert[i], 平面[k]) > 0) {
				有相交 = false;
				break;
			}
		}
		if(有相交) return true;
	}

	return false;
}

void f_surface_网格内点(S_Mesh* me, const Mat44f& mat, const S_Vec3Array* vert, S_BoolArray* 是内部, bool 反向) {
	switch (*me->m_顶点配置Flags) {
		case E_顶点组合标志::e_坐标_法线_UV: {
			S_VNT1* VNT = f_buf_VNT_ptr(*me->m_顶点);
			uvec3* index = (uvec3*)f_buf_UI32_ptr(*me->m_索引);

			uint32 num = me->m_索引->m_Mem.m_大小 / 3;
			for (uint32 i = 0; i < num; ++i) {
				VNT[index[i].x].vert;
				VNT[index[i].y].vert;
				VNT[index[i].z].vert;
			}

			break;
		}
	}
}

	

void f_mesh_顶点类型切换(S_Mesh* 目标, const S_Mesh* 源) {
	uint32 num = 源->m_顶点->m_Mem.m_大小;

	switch (*源->m_顶点配置Flags) {
	case E_顶点标志位::e_顶点坐标:
		*目标->m_顶点 = f_buf_alloc(S_Mesh::g_顶点v, num);
		break;
	case E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点颜色:
		*目标->m_顶点 = f_buf_alloc(S_Mesh::g_顶点vc, num);
		break;
	case E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点法线:
		*目标->m_顶点 = f_buf_alloc(S_Mesh::g_顶点vn, num);
		break;
	case E_顶点标志位::e_顶点坐标 | E_顶点标志位::e_顶点法线 | E_顶点标志位::e_顶点UV:
		*目标->m_顶点 = f_buf_alloc(S_Mesh::g_顶点vnt, num);
		break;
	}

	*目标->m_顶点配置Flags = *源->m_顶点配置Flags;
	f_buf_copy(*目标->m_顶点, *源->m_顶点);
}

VkAccelerationStructureKHR& f_mesh_get加速结构(S_VKMesh板载缓存* me) {
	f_buf_get加速结构(*me->m_底层光追加速结构);
	return *(VkAccelerationStructureKHR*)&(me->m_底层光追加速结构->m_As);

	auto* 绘图配置 = (S_绘图设备配置*)f_df_get绘图环境(me->m_Ctx);

	VkAccelerationStructureCreateInfoKHR 加速结构创建信息{};
	加速结构创建信息.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
	加速结构创建信息.buffer = ((S_VkArray缓存*)me->m_底层光追加速结构->m_Buf)->m_Data.m_Buf;
	加速结构创建信息.type = VkAccelerationStructureTypeKHR(f_getAPI光追加速缓存类型(me->m_底层光追加速结构->m_Buf->m_Type));
	加速结构创建信息.size = me->m_底层光追加速结构->m_Mem.m_大小;
	加速结构创建信息.offset = me->m_底层光追加速结构->m_Mem.m_偏移;

	if (me->m_光追加速结构) {
		绘图配置->vkDestroyAccelerationStructure(绘图配置->m_设备, me->m_光追加速结构, nullptr);
	}
	绘图配置->vkCreateAccelerationStructure(绘图配置->m_设备, &加速结构创建信息, nullptr, &me->m_光追加速结构);

	return me->m_光追加速结构;
}


void f_surface_构建光追底层加速结构(S_Mesh* me, E_物体类型 ObType) {
	auto* 绘图配置 = (S_绘图设备配置*)me->m_Ctx.m_绘图设备配置;


	VkAccelerationStructureGeometryKHR 几何体{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR };
	几何体.flags = VK_GEOMETRY_OPAQUE_BIT_KHR | VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR;
	几何体.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
	几何体.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
	几何体.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
	几何体.geometry.triangles.vertexStride = sizeof(S_VNT1);
	几何体.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;

	几何体.geometry.triangles.vertexData.deviceAddress = f_buf_getAddress(*(me->m_顶点));
	几何体.geometry.triangles.indexData.deviceAddress = f_buf_getAddress(*(me->m_索引));
	几何体.geometry.triangles.maxVertex = me->m_顶点->m_Mem.m_大小;

	assert(me->m_顶点->m_Mem.m_大小 > 0);



	std::vector<uint32>	 m_几何图元数量;
	VkAccelerationStructureBuildRangeInfoKHR* 加速体区间绑定 = (VkAccelerationStructureBuildRangeInfoKHR*)malloc(sizeof(VkAccelerationStructureBuildRangeInfoKHR));
	switch (ObType) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格: {
			uint32 tnum = me->m_索引->m_Mem.m_大小 / 3;
			assert(tnum > 1);
			加速体区间绑定->firstVertex = 0;
			加速体区间绑定->primitiveCount = tnum;
			加速体区间绑定->primitiveOffset = 0;
			加速体区间绑定->transformOffset = 0;

			m_几何图元数量.push_back(tnum);
			break;
		}
		case E_物体类型::t_区域光_方形: {
			加速体区间绑定->firstVertex = 0;
			加速体区间绑定->primitiveCount = 2;
			加速体区间绑定->primitiveOffset = 0;
			加速体区间绑定->transformOffset = 0;
			m_几何图元数量.push_back(2);
			break;
		}
		case E_物体类型::t_区域光_圆形: {
			加速体区间绑定->firstVertex = 4;
			加速体区间绑定->primitiveCount = 128;
			加速体区间绑定->primitiveOffset = 0;
			加速体区间绑定->transformOffset = 0;
			m_几何图元数量.push_back(128);
			break;
		}
	}





	VkAccelerationStructureBuildGeometryInfoKHR m_加速结构绑定几何信息 = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
	m_加速结构绑定几何信息.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
	m_加速结构绑定几何信息.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
	m_加速结构绑定几何信息.geometryCount = 1;
	m_加速结构绑定几何信息.pGeometries = &几何体;

	VkAccelerationStructureBuildSizesInfoKHR m_加速结构绑定大小信息 = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
	绘图配置->vkGetAccelerationStructureBuildSizes(绘图配置->m_设备,
											   VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
											   &m_加速结构绑定几何信息,
											   m_几何图元数量.data(),
											   &m_加速结构绑定大小信息);


	
	f_buf_gresize(*me->m_底层光追加速结构, m_加速结构绑定大小信息.accelerationStructureSize);
	S_板载缓存* 暂存缓冲区 = f_buf_create板载缓存(me->m_Ctx, E_板载缓存类型::e_SSBO, E_板载缓存类型::e_SSBO | E_板载缓存类型::e_着色端内存地址, 1, m_加速结构绑定大小信息.accelerationStructureSize);




	m_加速结构绑定几何信息.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
	m_加速结构绑定几何信息.dstAccelerationStructure = f_mesh_get加速结构((S_VKMesh板载缓存*)me);
	m_加速结构绑定几何信息.scratchData.deviceAddress = f_buf_getAddress(static_cast<S_VkArray缓存*>(暂存缓冲区));


	f_Draw_Begin(&me->m_Ctx, S_光追后端::m_加速结构创建命令缓存, S_光追后端::m_渲染Fence);
	绘图配置->vkCmdBuildAccelerationStructures((VkCommandBuffer)S_光追后端::m_加速结构创建命令缓存, 1, &m_加速结构绑定几何信息, &加速体区间绑定);
	f_Draw_end(&me->m_Ctx, S_光追后端::m_加速结构创建命令缓存, S_光追后端::m_渲染Fence, 3);


	f_buf_release板载缓存(暂存缓冲区);
	free(加速体区间绑定);




	if (!me->m_光追网格GPU地址引用.m_Buf) {
		me->m_光追网格GPU地址引用 = f_buf_alloc(S_Mesh::g_RtMesh, 1);
	}
	f_buf_网格引用_at(me->m_光追网格GPU地址引用) = {
		f_buf_getAddress(*me->m_顶点),
		f_buf_getAddress(*me->m_UV),
		f_buf_getAddress(*me->m_UV索引),
		f_buf_getAddress(*me->m_索引),
		f_buf_getAddress(*me->m_面),
		DEF_ObType_Mesh,
		0,
	};
}



















